package chabernac.android.draw;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class SurfaceViewAnimation extends SurfaceView {
	public SurfaceViewAnimation(Context context) {
		super(context);
	}

	public SurfaceViewAnimation(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public SurfaceViewAnimation(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	private SingleObjectQueue<AbstractDrawable> myQueue = new SingleObjectQueue<AbstractDrawable>();
	private float offsetX = 0;
	private float offsetY = 0;
	private float pivotX;
	private float pivotY;
	private boolean isRunning = false;
	private Thread myThread = null;
	private float myScale = 0.1F;
	private RectF myDrawingRect = new RectF();
	private Matrix myLastMatrix = new Matrix();
	private final Painter myPainter = new Painter();

	public void start() {
		isRunning = true;
		myThread = new Thread(myPainter);
		myThread.setPriority(Thread.MAX_PRIORITY);
		myThread.start();
	}

	public void stop() {
		isRunning = false;
		while (true) {
			try {
				myThread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			break;
		}
		myThread = null;
	}

	public void setTranslation(float difx, float dify) {
		offsetX += difx;
		offsetY += dify;
		// calculateDrawingRect();
	}

	public void setScale(float aScale, float aPivotX, float aPivotY) {
		float theOldScale = myScale;
		myScale *= aScale;

		float[] thePoint = new float[] { aPivotX, aPivotY };
		myLastMatrix.mapPoints(thePoint);

		offsetX = thePoint[0] * (theOldScale - myScale) + offsetX;
		offsetY = thePoint[1] * (theOldScale - myScale) + offsetY;
	}

	public void getDrawingRect(Rect aDrawingRect) {
		aDrawingRect.left = (int) Math.ceil(myDrawingRect.left);
		aDrawingRect.right = (int) Math.floor(myDrawingRect.right);
		aDrawingRect.top = (int) Math.ceil(myDrawingRect.top);
		aDrawingRect.bottom = (int) Math.floor(myDrawingRect.bottom);
	}

	public Matrix getTransformationMatrix() {
		return myLastMatrix;
	}

	public SingleObjectQueue<AbstractDrawable> getDrawingQueue() {
		return myQueue;
	}

	private class Painter implements Runnable {
		private final SurfaceHolder myHolder = getHolder();
		private AbstractDrawable myCurrentDrawable = null;

		@Override
		public void run() {
			while (isRunning) {
				if (myHolder.getSurface().isValid()) {
					Canvas theCanvas = myHolder.lockCanvas();
					theCanvas.translate(offsetX, offsetY);
					theCanvas.scale(myScale, myScale);

					RectF theRect = new RectF(0, 0, getWidth(), getHeight());
					Matrix theMatrix = theCanvas.getMatrix();
					float[] thePont = new float[] { 10, 10 };
					theMatrix.mapPoints(thePont);
					theMatrix.invert(myLastMatrix);
					myLastMatrix.mapRect(myDrawingRect, theRect);

					theCanvas.drawARGB(255, 0, 0, 0);

					AbstractDrawable theDrawable = myQueue.get();
					if (theDrawable != null) {
						myCurrentDrawable = theDrawable;
					}
					if (myCurrentDrawable != null) {
						myCurrentDrawable.paint(theCanvas, SurfaceViewAnimation.this);
					}
					myHolder.unlockCanvasAndPost(theCanvas);
				}
			}
		}
	}

}
